import yaml
import logging
import re
import requests
from kubernetes import client, config


def load_config(config_path):
    """
    加载配置文件
    :param config_path: 配置文件路径
    :return: 配置字典
    """
    try:
        with open(config_path, 'r', encoding='utf-8') as f:
            cfg = yaml.safe_load(f)
        return cfg
    except Exception as e:
        logging.error(f"Failed to load config file {config_path}: {e}")
        return {}


def setup_logging(cfg):
    """
    日志配置
    :param cfg: 配置字典
    """
    log_level = cfg.get('logging', {}).get('level', 'INFO').upper()
    log_format = cfg.get('logging', {}).get('format', '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    logging.basicConfig(level=log_level, format=log_format)


def parse_metrics(metrics):
    """
    解析内存使用率
    :param metrics: node-exporter接口
    :return:
    """
    try:
        logging.debug(f"Metrics data received: {metrics}")

        total_mem_match = re.search(r'node_memory_MemTotal_bytes\s+(\d+\.\d+e[+-]\d+)', metrics)
        available_mem_match = re.search(r'node_memory_MemAvailable_bytes\s+(\d+\.\d+e[+-]\d+)', metrics)

        if not total_mem_match or not available_mem_match:
            logging.error("Missing memory metrics in the data.")
            return 0

        total_mem = float(total_mem_match.group(1))
        available_mem = float(available_mem_match.group(1))

        mem_usage = ((total_mem - available_mem) / total_mem) * 100
        return round(mem_usage, 1)
    except Exception as e:
        logging.error(f"Error parsing metrics: {e}")
        return 0


def load_kube_config():
    """
    加载 Kubernetes 配置
    :return: CoreV1Api 实例和 CustomObjectsApi 实例的元组
    """
    try:
        config.load_incluster_config()
    except config.ConfigException:
        try:
            config.load_kube_config()
        except config.ConfigException as e:
            logging.error(f"Failed to load Kubernetes configuration: {e}")
            raise

    return client.CoreV1Api(), client.CustomObjectsApi(), client.AppsV1Api()


def get_node_metrics(url):
    """
    获取节点的指标数据。
    :param url: 节点的完整 URL
    :return: 指标数据
    """
    try:
        # Ensure the URL points to the /metrics endpoint
        if not url.endswith('/metrics'):
            url += '/metrics'

        response = requests.get(url)
        response.raise_for_status()
        metrics = response.text
        logging.debug(f"Metrics data fetched from {url}: {metrics}")
        return metrics
    except requests.RequestException as e:
        logging.error(f"Failed to fetch metrics from {url}: {e}")
        return None


def get_pod_mem_usages(custom_objects_api):
    """
    获取所有 Pod 的内存使用率。
    :param custom_objects_api: CustomObjectsApi 实例
    :return: 字典，键为 (namespace, pod_name)，值为内存使用量（MB）
    """
    try:
        metric_data = custom_objects_api.list_cluster_custom_object(
            group="metrics.k8s.io",
            version="v1beta1",
            plural="pods"
        )
        pod_mem_usages = {}
        # 单位转换
        for item in metric_data.get('items', []):
            namespace = item['metadata']['namespace']
            pod_name = item['metadata']['name']
            for container in item['containers']:
                mem_usage_str = container['usage']['memory']
                if mem_usage_str.endswith('Ki'):
                    mem_usage_bytes = int(mem_usage_str[:-2]) * 1024
                elif mem_usage_str.endswith('Mi'):
                    mem_usage_bytes = int(mem_usage_str[:-2]) * 1024 * 1024
                elif mem_usage_str.endswith('Gi'):
                    mem_usage_bytes = int(mem_usage_str[:-2]) * 1024 * 1024 * 1024
                else:
                    logging.error(f"Unknown memory unit in usage string: {mem_usage_str}")
                    continue
                mem_usage_mb = mem_usage_bytes / (1024 * 1024)
                pod_mem_usages[(namespace, pod_name)] = mem_usage_mb
        return pod_mem_usages
    except Exception as e:
        logging.error(f"Failed to fetch pod memory usages: {e}")
        return {}
